home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / progutil / dri2gnu.lzh / DRI2GNU.C < prev    next >
C/C++ Source or Header  |  1992-12-11  |  12KB  |  366 lines

  1. /* This is a 'quick n dirty' hack to convert DRI objects to the GNU.OUT format
  2.    used on the ATARI ST.
  3.     For problems contact
  4.     <Joerg.Hessdoerfer@EUROPA.rs.kp.dlr.de> (preferable adress!) or, if this
  5.     doesn't work, <Hessdorf@sun.ph-cip.uni-koeln.de> */
  6.  
  7. /* Copyright (C) 1992 Joerg Hessdoerfer, Cologne, Germany.
  8.    written by Joerg Hessdoerfer
  9.    
  10.    This program is free software; you can redistribute it and/or modify
  11.    it under the terms of the GNU General Public License as published by
  12.    the Free Software Foundation; either version 2, or (at your option)
  13.    any later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.    You should have received a copy of the GNU General Public License
  21.    along with this program; if not, write to the Free Software
  22.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include "gnu-out.h"
  27.  
  28. struct
  29. {
  30.     short magic;
  31.     long tsize;
  32.     long dsize;
  33.     long bsize;
  34.     long ssize;
  35.     char reserved[10];
  36. }ObjHeader;
  37.  
  38. /* pointers to DRI segments */
  39. short *txtbase,*database;
  40. short *txtfixup,*datafixup;
  41. char *symbase;
  42.  
  43. /* pointers & indices to GNU segments */
  44. struct exec GNUheader;
  45. int *symxtab;
  46. struct nlist *syment;
  47. char *symstrs;
  48. long symstrpos;
  49. struct relocation_info *textreloc,*datareloc;
  50. int textrelpos,datarelpos;
  51. int symentpos,validsym;
  52.  
  53. int main(int argc, char **argv)
  54. {
  55.     int i,width;
  56.  
  57.     if(argc<2)printf("Usage: %s file...\n",argv[0]);
  58.     else
  59.     {
  60.         for(i=1;i<argc;i++)
  61.         {
  62.             FILE *fp;
  63.             short *buffer;
  64.             int size,j;
  65.             
  66.             fp=fopen(argv[i],"rb");
  67.             if(!fp)
  68.             {
  69.                 printf("%s: can't open '%s'!\n",argv[0],argv[i]);
  70.                 exit(1);
  71.             }
  72.             fread(&ObjHeader,1,sizeof(ObjHeader),fp);
  73.             if(ObjHeader.magic!=0x601a)
  74.             {
  75.                 printf("%s: '%s' is no standard DRI object. Sorry.\n",argv[0],argv[i]);
  76.                 fclose(fp);
  77.                 exit(2);
  78.             }
  79.  
  80.             N_SET_INFO(GNUheader,OMAGIC,0,0);
  81.             GNUheader.a_text=ObjHeader.tsize;
  82.             GNUheader.a_data=ObjHeader.dsize;
  83.             GNUheader.a_bss=ObjHeader.bsize;
  84.             GNUheader.a_syms=(ObjHeader.ssize/14)*sizeof(struct nlist);
  85.             GNUheader.a_trsize=0; /* we don't know the size yet, compute it later! */
  86.             GNUheader.a_drsize=0; /* same goes here! */
  87.             GNUheader.a_entry=0; /* always zero for object files! */
  88.             
  89.             size=2*ObjHeader.tsize+2*ObjHeader.dsize+ObjHeader.ssize;
  90.             if((buffer=malloc(size))==NULL)
  91.             {
  92.                 printf("%s: not enough memory! Stop!\n",argv[0]);
  93.                 fclose(fp);
  94.                 exit(3);
  95.             }
  96.  
  97.             fread(buffer,1,size,fp);
  98.             fclose(fp);
  99.  
  100.             /* now calculate the DRI object segment starts */
  101.             txtbase=buffer;
  102.             txtfixup=&buffer[(ObjHeader.tsize+ObjHeader.dsize+ObjHeader.ssize)/2];
  103.             database=&buffer[ObjHeader.tsize/2];
  104.             datafixup=&buffer[ObjHeader.tsize+(ObjHeader.dsize+ObjHeader.ssize)/2];
  105.             symbase=(char *)&buffer[(ObjHeader.tsize+ObjHeader.dsize)/2];
  106.  
  107.             symstrs=malloc((ObjHeader.ssize/14)*10); /* a DRI sym entry is 14 bytes wide,
  108.                                                                       it's name is restricted to 8 bytes */
  109.             syment=malloc(GNUheader.a_syms);
  110.             symxtab=malloc((ObjHeader.ssize/14)*sizeof(int));
  111.             
  112.             if(!symstrs || !syment || !symxtab)
  113.             {
  114.                 printf("%s: not enough memory! Stop!\n",argv[0]);
  115.                 exit(1);
  116.             }
  117.  
  118.             symstrpos=4; /* IMPORTANT!!! A value of 0 is considered to refer to NO name at all! */
  119.             /* Besides, it could have been documented that the size of the string-table is noted
  120.                in the longword immediately before it!! ( therefore the '4'!!!!) */
  121.             
  122.             for(j=0; j<((ObjHeader.ssize/14)*10);j++)symstrs[j]=0; /* clear stringtable first! */
  123.  
  124.             symentpos=0;                        
  125.             for(j=0; j<ObjHeader.ssize;j+=14)
  126.             {
  127.                 switch((unsigned char)(symbase[j+8]))
  128.                 {
  129.                     case 0x88: /* external */
  130.                     case 0xa8:
  131.                         syment[symentpos].n_type=N_UNDF | N_EXT;
  132.                         syment[symentpos].n_value=0;
  133.                         validsym=1;
  134.                         break;
  135.                     case 0x81: /* local syms */
  136.                     case 0x82:
  137.                     case 0x84:
  138.                         validsym=0;    /* ignore them for now, as they're not needed for linking! */
  139.                         break;    
  140.                     case 0xa1: /* BSS */
  141.                         syment[symentpos].n_type=N_BSS | N_EXT;
  142.                         syment[symentpos].n_value=*(long *)&symbase[j+10];
  143.                         validsym=1;
  144.                         break;
  145.                     case 0xa2: /* TEXT */
  146.                         syment[symentpos].n_type=N_TEXT | N_EXT;
  147.                         syment[symentpos].n_value=*(long *)&symbase[j+10];
  148.                         validsym=1;
  149.                         break;
  150.                     case 0xa4: /* DATA */
  151.                         syment[symentpos].n_type=N_DATA | N_EXT;
  152.                         syment[symentpos].n_value=*(long *)&symbase[j+10]+GNUheader.a_text;
  153.                         /* now here's a real goodie: in a.out objects, the address of a symbol
  154.                            in the data segment refers to its address plus the size of the text
  155.                            segment. Man, I can't tell ya how I hate this! (Of course that feature's
  156.                            not documented!!!) */
  157.                         validsym=1;
  158.                         break;
  159.                     default:
  160.                         printf("%s: unknown symbol type '%x' at %d! Ignored!\n",
  161.                                 argv[0],(unsigned int)symbase[j+8],symentpos);
  162.                         validsym=0;
  163.                         break;
  164.                 }
  165.                 if(validsym)
  166.                 {
  167.                     symxtab[j/14]=symentpos;    /* build up cross-refs */
  168.                     strncpy(&symstrs[symstrpos],&symbase[j],8);
  169.                     symstrs[symstrpos+strlen(&symstrs[symstrpos])]=0;
  170.                     syment[symentpos].n_un.n_strx=symstrpos;
  171.                     symstrpos+=strlen(&symstrs[symstrpos])+1;
  172.                     syment[symentpos].n_other=0;
  173.                     syment[symentpos].n_desc=0;
  174.                     symentpos++;
  175.                 }
  176.             }
  177.  
  178.             *(long *)symstrs=symstrpos;
  179.             GNUheader.a_syms=symentpos*sizeof(struct nlist); /* correct symbol table size */
  180.             
  181.             for(j=0;j<(ObjHeader.tsize/2);j++)
  182.             {
  183.                 /* compute a_trsize */
  184.                 switch(txtfixup[j] & 0x07)
  185.                 {
  186.                     case 0:        /* ignore zero types (no reloc) and LW markers,
  187.                                         as well as instructions */
  188.                     case 5:        
  189.                     case 7:        
  190.                         break;
  191.                     default:
  192.                         GNUheader.a_trsize+=sizeof(struct relocation_info);
  193.                         break;
  194.                 }
  195.             }
  196.             
  197.             for(j=0;j<(ObjHeader.dsize/2);j++)
  198.             {
  199.                 /* compute a_drsize */
  200.                 switch(datafixup[j] & 0x07)
  201.                 {
  202.                     case 0:        /* ignore zero types (no reloc) and LW markers,
  203.                                         as well as instructions */
  204.                     case 5:        
  205.                     case 7:        
  206.                         break;
  207.                     default:
  208.                         GNUheader.a_drsize+=sizeof(struct relocation_info);
  209.                         break;
  210.                 }
  211.             }
  212.  
  213.             textreloc=malloc(GNUheader.a_trsize);
  214.             datareloc=malloc(GNUheader.a_drsize);
  215.             textrelpos=datarelpos=0;
  216.             
  217.             if(!textreloc || !datareloc)
  218.             {
  219.                 printf("%s: not enough memory! Stop!\n",argv[0]);
  220.                 exit(1);
  221.             }
  222.  
  223.             width=1; /* default word size is 16bit */
  224.             
  225.             for(j=0;j<(ObjHeader.tsize/2);j++)
  226.             {
  227.                 switch(txtfixup[j] & 0x07)
  228.                 {
  229.                     case 0:
  230.                         break;
  231.                     case 1: /* absolute DATA reloc */
  232.                         textreloc[textrelpos].r_address=((width==2) ? j*2 - 2 : j*2);
  233.                         textreloc[textrelpos].r_symbolnum=N_DATA;
  234.                         textreloc[textrelpos].r_pcrel=0;
  235.                         textreloc[textrelpos].r_length=width; width=1;
  236.                         textreloc[textrelpos].r_extern=0;
  237.                         textreloc[textrelpos++].r_pad=0;
  238.                         break;
  239.                     case 2: /* absolute TEXT reloc */
  240.                         textreloc[textrelpos].r_address=((width==2) ? j*2 - 2 : j*2);
  241.                         textreloc[textrelpos].r_symbolnum=N_TEXT;
  242.                         textreloc[textrelpos].r_pcrel=0;
  243.                         textreloc[textrelpos].r_length=width; width=1;
  244.                         textreloc[textrelpos].r_extern=0;
  245.                         textreloc[textrelpos++].r_pad=0;
  246.                         break;
  247.                     case 3: /* absolute BSS reloc */
  248.                         textreloc[textrelpos].r_address=((width==2) ? j*2 - 2 : j*2);
  249.                         textreloc[textrelpos].r_symbolnum=N_BSS;
  250.                         textreloc[textrelpos].r_pcrel=0;
  251.                         textreloc[textrelpos].r_length=width; width=1;
  252.                         textreloc[textrelpos].r_extern=0;
  253.                         textreloc[textrelpos++].r_pad=0;
  254.                         break;
  255.                     case 4: /* absolute EXTERN reloc */
  256.                         textreloc[textrelpos].r_address=((width==2) ? j*2 - 2 : j*2);
  257.                         textreloc[textrelpos].r_symbolnum=symxtab[(txtfixup[j] >> 3)];
  258.                         textreloc[textrelpos].r_pcrel=0;
  259.                         textreloc[textrelpos].r_length=width; width=1;
  260.                         textreloc[textrelpos].r_extern=1